import 'package:flutter/material.dart';
import 'bitmap.dart';
import 'canvas_view.dart';
import 'curtain_light_model.dart';

class CanvasPreviewWidget extends StatelessWidget {
  const CanvasPreviewWidget({
    Key? key,
    required this.bitmap,
    required this.directionType,
    required this.frameKey,
  }) : super(key: key);

  final Bitmap bitmap;
  final DiyDeviceDirectionType directionType;
  final GlobalKey<CurtainMatrixViewState> frameKey;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (_, constraints) {
        return SizedBox(
          width: constraints.maxWidth,
          height: constraints.maxHeight,
          child: CustomPaint(
            size: Size(constraints.maxWidth, constraints.maxHeight),
            painter: CanvasPreviewPainter(
              bitmap: bitmap,
              directionType: directionType,
              frameKey: frameKey,
            ),
          ),
        );
      },
    );
  }
}

num getMaxValue(num a, num b) => a > b ? a : b;

class CanvasPreviewPainter extends CustomPainter {
  CanvasPreviewPainter({
    required this.bitmap,
    required this.directionType,
    required this.frameKey,
  }) {
    max = getMaxValue(bitmap.x, bitmap.y).toInt();
    mPaint = Paint()
      ..strokeWidth = 0.1
      ..color = Colors.transparent
      ..style = PaintingStyle.stroke;
  }

  Bitmap bitmap;
  DiyDeviceDirectionType directionType;

  late Paint mPaint;
  late int max;

  late GlobalKey<CurtainMatrixViewState> frameKey;

  @override
  void paint(Canvas canvas, Size size) {
    double side = size.width / max;
    double dx = 0;
    double dy = 0;
    if (directionType == DiyDeviceDirectionType.vertical) {
      dx = (size.width * 0.5) - (side * bitmap.x * 0.5);
    } else {
      dy = (size.width * 0.5) - (side * bitmap.y * 0.5);
    }
    canvas.translate(dx, dy);
    drawMatrix(side, canvas);
    drawPixels(side, canvas);
    // drawFrame(side, canvas);
  }

  void drawMatrix(double side, Canvas canvas) {
    double lastX = 0;
    for (int i = 0; i <= bitmap.x; i++) {
      Offset startX = Offset(lastX, 0);
      Offset endX = Offset(lastX, bitmap.y * side);
      canvas.drawLine(startX, endX, mPaint);
      lastX += side;
    }
    double lastY = 0;
    for (int i = 0; i <= bitmap.y; i++) {
      Offset startY = Offset(0, lastY);
      Offset endY = Offset(bitmap.x * side, lastY);
      canvas.drawLine(startY, endY, mPaint);
      lastY += side;
    }
  }

  void drawPixels(double side, Canvas canvas) {
    Paint transPaint = Paint();
    for (int i = 0; i < bitmap.x; i++) {
      for (int j = 0; j < bitmap.y; j++) {
        transPaint.color = bitmap.getPixel(dx: i, dy: j);
        double left = i * side;
        double top = j * side;
        double right = (i + 1) * side;
        double bottom = (j + 1) * side;
        canvas.drawRect(Rect.fromLTRB(left, top, right, bottom), transPaint);
      }
    }
  }

  void drawFrame(double side, Canvas canvas) {
    Size canvasSize = Size(side * bitmap.x, side * bitmap.y);
    Paint framePaint = Paint()..color = Color(0xff00ff00);
    Size sizeBox = frameKey.currentState!.sizeBox;

    /// LEFT
    double leftDx1 = 0.0;
    double leftDy1 = 0.0;
    double leftDx2 = 0.0;
    double leftDy2 = 0.0;
    Offset leftStart = Offset(leftDx1, leftDy1);
    Offset leftEnd = Offset(leftDx2, canvasSize.height);
    canvas.drawLine(leftStart, leftEnd, framePaint);

    /// TOP
    double topDx1 = 0.0;
    double topDy1 = 0.0;
    double topDx2 = 0.0;
    double topDy2 = 0.0;
    Offset topStart = Offset(topDx1, topDy1);
    Offset topEnd = Offset(topDx2, topDy2);
    canvas.drawLine(topStart, topEnd, framePaint);

    /// RIGHT
    double rightDx1 = 0.0;
    double rightDy1 = 0.0;
    double rightDx2 = 0.0;
    double rightDy2 = 0.0;
    Offset rightStart = Offset(rightDx1, rightDy1);
    Offset rightEnd = Offset(rightDx2, rightDy2);
    canvas.drawLine(rightStart, rightEnd, framePaint);

    /// BOTTOM
    double bottomDx1 = 0.0;
    double bottomDy1 = 0.0;
    double bottomDx2 = 0.0;
    double bottomDy2 = 0.0;
    Offset bottomStart = Offset(bottomDx1, bottomDy1);
    Offset bottomEnd = Offset(bottomDx2, bottomDy2);
    canvas.drawLine(bottomStart, bottomEnd, framePaint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
